unit uNetDrag ;

interface

uses
  Classes,
  Controls,
  Types,
  uBasic,
  uObjects,
  uPlacement,
  GDIPAPI,
  GDIPOBJ ;

type
  TDraggerHelper = class( TMedaHelper )
  private
    fGrid : integer ;
    fOffset : TGPPointF ;
  public
    constructor Create( aGrid : integer ; aOffset : TGPPointF ) ;
    destructor Destroy ; override ;
    function Move( aView : TMedaView ; Shift : TShiftState ;
      aPos : TGPPointF ) : TCursor ; virtual ;
  end ;

  TLineDragState = ( ldsNone, ldsP1, ldsP2, ldsP12 ) ;
  TLineDragger = class( TDraggerHelper )
  private
    fState : TLineDragState ;
  public
    function Move( aView : TMedaView ; Shift : TShiftState ;
      aPos : TGPPointF ) : TCursor ; override ;
  end ;

  TTrackDragger = class( TLineDragger )
  public
    function Move( aView : TMedaView ; Shift : TShiftState ;
      aPos : TGPPointF ) : TCursor ; override ;
  end ;

  TPinDragger = class( TDraggerHelper )
  public
    function Move( aView : TMedaView ; Shift : TShiftState ;
      aPos : TGPPointF ) : TCursor ; override ;
  end ;

  TBoxDragger = class( TDraggerHelper )
  public
    function Move( aView : TMedaView ; Shift : TShiftState ;
      aPos : TGPPointF ) : TCursor ; override ;
  end ;

implementation

{ TDraggerHelper }

constructor TDraggerHelper.Create( aGrid : integer ; aOffset : TGPPointF ) ;
begin
  fGrid := aGrid ;
  fOffset := aOffset ;
end ;

destructor TDraggerHelper.Destroy ;
begin

  inherited ;
end ;

function TDraggerHelper.Move( aView : TMedaView ; Shift : TShiftState ;
  aPos : TGPPointF ) : TCursor ;
begin
  Result := crNo ;
end ;

{ TPinDragger }

function TPinDragger.Move( aView : TMedaView ; Shift : TShiftState ;
  aPos : TGPPointF ) : TCursor ;
var
  iTrans            : TMedaTransform ;
  iObject           : TMedaObject ;
  iT                : TGPPointF ;
  iPin              : TMedaPin ;
begin
  Result := inherited Move( aView, Shift, aPos ) ;
  if ( ssCtrl in Shift ) then begin
    Result := ord( crHandClosed ) ;
    iObject := aView.Owner ;
    iPin := iObject as TMedaPin ;
    iTrans := iPin.Transforms[ 0 ] ;
    iT.X := aPos.X - iTrans.Position.X ;
    iT.Y := aPos.Y - iTrans.Position.Y ;
    ScaleDown( iT, fGrid ) ;
    ScaleUp( iT, fGrid ) ;
    iPin.Offset := iT ;
  end ;
end ;

{ TLineDragger }

function TLineDragger.Move( aView : TMedaView ; Shift : TShiftState ;
  aPos : TGPPointF ) : TCursor ;
var
  iWire             : TMedaWire ;
  p1, p2, p, o, e   : TGPPointF ;
begin
  if not ( aView is TMSPWire ) then begin
    Result := crNo ;
    Exit ;
  end ;

  iWire := aView.Owner as TMedaWire ;
  p.X := aPos.X - fOffset.X ;
  p.Y := aPos.Y - fOffset.Y ;
  ScaleDown( aPos, fGrid ) ;
  ScaleUp( aPos, fGrid ) ;
  iWire.GetPoints( p1, p2 ) ;
  e.X := p2.X - p1.X ;
  e.Y := p2.Y - p1.Y ;
  case fState of
    ldsNone : begin
        o := MakePoint( 0.0, 0.0 ) ;
        Result := ord( crHandOpen ) ;
        if Distance( fOffset, o ) < fGrid then
          fState := ldsP1
        else if Distance( fOffset, e ) < fGrid then
          fState := ldsP2
        else begin
          fState := ldsP12 ;
        end ;
      end ;
    ldsP1 : begin
        iWire.SetPoints( aPos, p2 ) ;
        Result := ord( crHandOpen ) ;
      end ;
    ldsP2 : begin
        iWire.SetPoints( p1, aPos ) ;
        Result := ord( crHandOpen ) ;
      end ;
  else
    ScaleDown( p, fGrid ) ;
    ScaleUp( p, fGrid ) ;
    GPOffsetPoint( e, p ) ;
    iWire.SetPoints( p, e ) ;
    Result := ord( crHandClosed ) ;
  end ;
end ;

{ TTrackDragger }

function TTrackDragger.Move( aView : TMedaView ; Shift : TShiftState ;
  aPos : TGPPointF ) : TCursor ;
var
  iTrack            : TMedaTrack ;
  p1, p2, p, o, e   : TGPPointF ;
begin
  if not ( aView is TMSPTrack ) then begin
    Result := crNo ;
    Exit ;
  end ;

  iTrack := aView.Owner as TMedaTrack ;
  p.X := aPos.X - fOffset.X ;
  p.Y := aPos.Y - fOffset.Y ;
  ScaleDown( aPos, fGrid ) ;
  ScaleUp( aPos, fGrid ) ;
  iTrack.GetPoints( p1, p2 ) ;
  case fState of
    ldsNone : begin
        o := MakePoint( 0.0, 0.0 ) ;
        e.X := p2.X - p1.X ;
        e.Y := p2.Y - p1.Y ;
        Result := ord( crHandOpen ) ;
        if Distance( fOffset, o ) < fGrid then
          fState := ldsP1
        else if Distance( fOffset, e ) < fGrid then
          fState := ldsP2
        else begin
          fState := ldsP12 ;
        end ;
      end ;
    ldsP1 : begin
        iTrack.SetPoints( aPos, p2 ) ;
        Result := ord( crHandOpen ) ;
      end ;
    ldsP2 : begin
        iTrack.SetPoints( p1, aPos ) ;
        Result := ord( crHandOpen ) ;
      end ;
  else
    ScaleDown( p, fGrid ) ;
    ScaleUp( p, fGrid ) ;
    iTrack.Position := p ;
    Result := ord( crHandClosed ) ;
  end ;
end ;

{ TBoxDragger }

function TBoxDragger.Move( aView : TMedaView ; Shift : TShiftState ;
  aPos : TGPPointF ) : TCursor ;
var
  iTrans            : TMedaTransform ;
  iObject           : TMedaObject ;
begin
  Result := ord( crHandClosed ) ;
  iObject := aView.Owner ;
  aPos.X := aPos.X - fOffset.X ;
  aPos.Y := aPos.Y - fOffset.Y ;
  ScaleDown( aPos, fGrid ) ;
  ScaleUp( aPos, fGrid ) ;
  iTrans := iObject.Transforms[ 0 ] ;
  iTrans.Position := aPos ;
  iObject.Transforms[ 0 ] := iTrans ;
end ;

end.

